package com.sign.demo.constant;

import lombok.Data;
import lombok.var;

import java.io.Serializable;
import java.lang.reflect.Field;
import java.math.BigDecimal;
import java.sql.Timestamp;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;

@Data
public class ApiResult<T> implements Serializable {
    //"Code 成功：0000 失败：其他错误码")
    private String code = "0000";
    // "返回消息")
    private String message = "成功";
    // "返回数据")
    private T data;


    private static final String defaultStr = "";
    private static final Date defaultDate = new Date();
    private static final BigDecimal defaultDecimal = new BigDecimal(0);
    private static final Timestamp defaultTimestamp = new Timestamp(new Date().getTime());
    private static final Boolean defaultBoolean = false;

    /**
     * 返回成功 不自动填充null
     *
     * @param data
     * @param <T>
     * @return
     */
    public static <T> ApiResult<T> successRaw(T data) {
        ApiResult<T> result = new ApiResult<>();
        result.setData(data);
        result.setCode("0000");
        return result;
    }

    /**
     * 自动填充null
     *
     * @param data
     * @param <T>
     * @return
     */
    public static <T> ApiResult<T> success(T data) {
        ApiResult<T> result = new ApiResult<>();
        setDefaultValue(data);
        result.setData(data);
        result.setCode("0000");
        return result;
    }

    public static ApiResult<Boolean> success() {
        ApiResult<Boolean> result = new ApiResult<>();
        result.setData(true);
        result.setCode("0000");
        return result;
    }


    public static <T> ApiResult<T> fail(IMessage errorCode) {
        return fail(errorCode.getCode(), errorCode.getCategory());
    }

    public static <T> ApiResult<T> fail(String code, String message) {
        ApiResult<T> result = new ApiResult<>();
        result.setCode(code);
        result.setMessage(message);
        return result;
    }

    //赋默认值
    public static void setDefaultValue(Object object) {
        try {
            if (object == null) {
                return;
            }
            Class clazz = object.getClass();
            if (List.class.isAssignableFrom(clazz)) {
                ((List) object).forEach(ApiResult::setDefaultValue);
                return;
            }

            Field[] fields = new Field[clazz.getDeclaredFields().length + clazz.getSuperclass().getDeclaredFields().length];
            System.arraycopy(clazz.getDeclaredFields(), 0, fields, 0, clazz.getDeclaredFields().length);
            System.arraycopy(clazz.getSuperclass().getDeclaredFields(), 0, fields, clazz.getDeclaredFields().length, clazz.getSuperclass().getDeclaredFields().length);

            for (int i = 0; i < fields.length; i++) {
                Field field = fields[i];
                Class fieldClass = field.getType();
                field.setAccessible(true); //设置访问权限

                var data = field.get(object);
                if (data != null) {
                    if (List.class.isAssignableFrom(data.getClass())) {
                        setDefaultValue(data);
                    }
                    continue;
                }
                if (fieldClass == Integer.class) {
                    field.set(object, defaultDecimal.intValue());
                } else if (fieldClass == Long.class) {
                    field.set(object, defaultDecimal.longValue());
                } else if (fieldClass == Float.class) {
                    field.set(object, defaultDecimal.doubleValue());
                } else if (fieldClass == BigDecimal.class) {
                    field.set(object, defaultDecimal);
                } else if (fieldClass == Date.class) {
                    field.set(object, defaultDate);
                } else if (fieldClass == String.class) {
                    field.set(object, defaultStr); // 设置值
                } else if (fieldClass == Timestamp.class) {
                    field.set(object, defaultTimestamp);
                } else if (fieldClass == Boolean.class) {
                    field.set(object, defaultBoolean);
                } else if (List.class.isAssignableFrom(fieldClass)) {
                    field.set(object, new ArrayList<>());
                }

            }
        } catch (Exception e) {
            e.printStackTrace();
            System.out.println(e.getMessage());
        }
    }
}
